use std::sync::Arc;
use std::time::Instant;

use futures::future::join_all;
use futures::TryFutureExt;
use lazy_static::lazy_static;
use regex::Regex;
use sea_orm::Database;
use taos::{AsyncTBuilder, TaosBuilder};
use tracing::info;
use crate::repo::point_group_repo::PointGroupRepo;
use crate::repo::xun_you_repo::XunYouRepo;

use crate::repo::point_repo::PointRepo;
use crate::repo::point_rlt_point_group_repo::PointRltPointGroupRepo;
use crate::repo::system_repo::SystemRepo;
use crate::repo::td_engine_repo::TDengineRepo;
use crate::util_entity::config::{AppSettings, Config};



pub struct AppState {
    pub appsettings: AppSettings,
    pub machine_config: Config,
    pub point_repo: PointRepo,
    pub point_group_repo: PointGroupRepo,
    pub system_repo: SystemRepo,
    pub td_engine_repo: TDengineRepo,
    pub cld_workingcondition_repo: XunYouRepo,
    pub point_rlt_point_group_repo: PointRltPointGroupRepo,
}

impl AppState {
    pub async fn new(appsettings: AppSettings, config: Config) -> Self {
        let start = Instant::now();

        let db_futures: Vec<_> = config.cfg.iter().enumerate().map(|(index, cfg)| {
            let db_conn_str = cfg.mysql.clone();
            info!("{}号机 mysql 连接字符串为: {}", index + 1, db_conn_str);
            Database::connect(db_conn_str.clone())
        }).collect();

        let dbs: Vec<_> = join_all(db_futures)
            .await
            .into_iter()
            .map(|db| db.unwrap_or_else(|e| panic!("mysql 数据库连接失败：{}", e)))
            .collect();

        let dbs = Arc::new(dbs);
        let duration = start.elapsed();
        info!("建立mysql 连接耗时为 :{:?}", duration);

        let start = Instant::now();
        // 建立 taos 连接
        let taos_futures: Vec<_> = config.cfg.iter().enumerate().map(|(index, cfg)| {
            let dsn = format!("taos://{}:{}@{}:{}/{}", cfg.user, cfg.password, cfg.host, cfg.port, cfg.database);
            info!("{}号机 taos 连接字符串为: {}", index + 1, dsn);
            async move {
                let builder = TaosBuilder::from_dsn(&dsn).map_err(|e| format!("创建 TaosBuilder 失败：{}", e))?;
                builder.build().await.map_err(|e| format!("{}号机 taos 数据库连接失败：{}", index + 1, e))
            }
        }).collect();

        // let taos = Vec::new();
        let taos: Vec<_> = join_all(taos_futures)
            .await
            .into_iter()
            .map(|db| db.unwrap_or_else(|e| panic!("taos 数据库连接失败：{}", e)))
            .collect();

        let duration = start.elapsed();
        info!("建立taos 连接耗时为 :{:?}", duration);

        Self {
            appsettings,
            machine_config: config,
            point_repo: PointRepo::new(Arc::clone(&dbs)),
            point_group_repo: PointGroupRepo::new(Arc::clone(&dbs)),
            system_repo: SystemRepo::new(Arc::clone(&dbs)),
            cld_workingcondition_repo: XunYouRepo::new(Arc::clone(&dbs)),
            td_engine_repo: TDengineRepo::new(taos),
            point_rlt_point_group_repo: PointRltPointGroupRepo::new(Arc::clone(&dbs)),
        }
    }
}